<template>
  <el-container style="background: #fff">
    <el-dialog
      v-if="dialogVisible"
      title="上传封面"
      :visible.sync="dialogVisible"
      width="30%"
      :destroy-on-close="true"
    >
      <el-form
        ref="ruleForm"
        :model="cover"
        :rules="rules"
        label-width="100px"
        class="demo-ruleForm"
      >
        <el-form-item label="名称" prop="name">
          <el-input v-model="cover.name" />
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <el-upload
            class="upload-demo"
            :headers="myHeaders"
            :action="apiUrl + '/index/upload'"
            :on-success="handleSuccess"
            :limit="1"
          >
            <el-button size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="uploadCover('ruleForm')"
            >保存</el-button
          >
          <el-button @click="resetForm('ruleForm')">重置</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <el-header style="border-bottom: 1px solid #e2e2e2; height: 40px">
      <el-row style="height: 100%">
        <el-col :span="3">
          <h2 style="margin: 5px 0px 0px 0px;">FreePoster</h2>
        </el-col>
        <el-col
          :span="6"
          style="font-size: 12px;margin-top: 13px;cursor: pointer;color: #f84311;"
        >
          <div @click="showUpload"><i class="el-icon-upload" /> 上传封面</div>
        </el-col>
        <el-col :span="10" class="header-tool">
          <div style="cursor: pointer; font-size: 12px" @click="download">
            <i class="el-icon-download" /> 下载
          </div>

          <div style="cursor: pointer; font-size: 12px" @click="save">
            <i class="el-icon-coin" /> 保存
          </div>
          <div style="cursor: pointer; font-size: 12px" @click="preview">
            <i class="el-icon-view" /> 预览
          </div>
          <div
            :style="{
              cursor: 'pointer',
              'font-size': '12px',
              color: '#f84311'
            }"
            @click="delItem"
          >
            <i class="el-icon-delete" /> 删除
          </div>
          <div
            :style="{
              cursor: 'pointer',
              'font-size': '12px',
              color: formData.item.length == 0 ? '#C2C2C2' : '#000'
            }"
            @click="back"
          >
            <i class="el-icon-refresh-left" /> 撤销
          </div>
        </el-col>
      </el-row>
    </el-header>
    <el-main class="container" style="padding: 0; background: #fff">
      <el-row class="content-box">
        <el-col :span="6" class="menu">
          <el-tabs
            tab-position="left"
            v-model="source_tab"
            style="height: calc(100vh - 115px); background: #fff"
            @tab-click="handleTabClick"
          >
            <el-tab-pane label="海报" name="data">
              <div class="list-wrapper">
                <div class="list">
                  <div
                    v-for="(item, index) in posterList"
                    :key="index"
                    class="free-poster"
                    @click="diy(item.id)"
                  >
                    <div :title="item.name" class="free-poster-title">
                      {{ item.name }}
                    </div>
                    <img :src="item.preview" />
                  </div>
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane label="封面" name="cover">
              <div class="list-wrapper">
                <div class="list">
                  <div
                    v-for="(item, index) in coverList"
                    :key="index"
                    class="free-poster"
                    @click="coverDiy(item)"
                  >
                    <div :title="item.name" class="free-poster-title">
                      {{ item.name }}
                    </div>
                    <i
                      class="el-icon-delete cover-del"
                      @click="delCover(item.id)"
                    />
                    <img :src="item.source" class="cover_img" />
                  </div>
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane label="组件" name="widget">
              <div class="list-wrapper">
                <div class="list">
                  <div class="item" @click="addItem('text')">
                    <i class="el-icon-edit" />
                    <div class="item-desc">
                      <h3 style="margin-left: 20px">文字</h3>
                      <p>点击创建</p>
                    </div>
                  </div>

                  <div class="item" @click="addItem('image')">
                    <i class="el-icon-picture" />
                    <div class="item-desc">
                      <h3 style="margin-left: 20px">图片</h3>
                      <p>点击创建</p>
                    </div>
                  </div>

                  <div class="item" @click="addItem('qrcode')">
                    <i class="el-icon-s-grid" />
                    <div class="item-desc">
                      <h3 style="margin-left: 20px">二维码</h3>
                      <p>点击创建</p>
                    </div>
                  </div>
                </div>
              </div>
            </el-tab-pane>
          </el-tabs>
        </el-col>
        <el-col :span="13" class="poster-view">
          <div class="free-editor-wrapper" :style="wrapper_style">
            <div ref="poster" class="free-poster-bg" :style="bg_style">
              <VueDragResize
                v-for="(item, index) in formData.item"
                :key="item.uuid"
                :w="calcSize(item.w)"
                :h="calcSize(item.h)"
                :x="calcSize(item.x)"
                :y="calcSize(item.y)"
                :is-active="index === nowFormIndex"
                @dragging="dragging"
                @resizing="resizing"
                @activated="onActivated(index)"
                @deactivated="onDeactivated(index)"
              >
                <div
                  v-if="item.t === 'text'"
                  :style="{
                    width: '100%',
                    height: '100%',
                    'font-size': calcSize(item.s) + 'px',
                    'font-family': item.fn,
                    color: item.c,
                    //'text-align': item.a,
                    //'white-space': item.warp ? 'break-spaces' : 'pre',
                    'line-height': 'calc(1em + 4px)'
                  }"
                >
                  {{ item.v }}
                </div>
                <img
                  v-if="item.t === 'image'"
                  :src="item.v"
                  style="width: 100%; height: 100%"
                />
                <div
                  v-if="item.t === 'qrcode'"
                  :id="'qrcode' + index"
                  :ref="'qrcode' + index"
                  style="width: 100%; height: 100%"
                />
              </VueDragResize>
            </div>
          </div>
          <div class="free-editor-bottom-bar">
            <i class="el-icon-remove" @click="changeSize(1)" />
            <span class="scale-num">{{ resize }}%</span>
            <i class="el-icon-circle-plus" @click="changeSize(2)" />
          </div>
        </el-col>
        <el-col :span="5" class="free-poster-tools" style="background: #fff">
          <el-tabs v-model="setting_tab">
            <el-tab-pane label="海报设置" name="base_setting">
              <base-form :formdata="formData" @baseUpdate="baseUpdate" />
            </el-tab-pane>
            <el-tab-pane label="组件设置" name="widget_setting">
              <Widget
                :formdata="nowWidget"
                :index="nowFormIndex"
                @baseUpdate="baseUpdate"
                @changeColor="changeColor"
                @changeQrcode="changeQrcode"
              />
            </el-tab-pane>
          </el-tabs>
        </el-col>
      </el-row>
    </el-main>
    <!-- 预览 -->
    <el-image-viewer
      v-if="previewImg"
      :on-close="closeViewer"
      :url-list="srcList"
    />
  </el-container>
</template>

<script>
import BaseForm from './BaseForm.vue'
import Widget from './Widget.vue'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
import QRCode from 'qrcodejs2'
import materialApi from '../api/material.js'
import posterApi from '../api/poster.js'

export default {
  name: 'Designer',
  components: {
    BaseForm,
    Widget,
    ElImageViewer
  },
  data () {
    return {
      apiUrl: '',
      dialogVisible: false,
      previewImg: false,
      url: '',
      srcList: [],
      source_tab: 'data',
      setting_tab: 'base_setting',
      nowWidget: {},
      cover: {
        name: '',
        source: '',
        width: 0,
        height: 0,
        type: 'png'
      }, // 封面
      formData: {
        name: '',
        type: 'jpg',
        qulity: 80,
        width: 750,
        height: 1333,
        activeName: 'img',
        color: '#fff',
        img_src: '',
        item: []
      },
      myHeaders: { Authorization: 'Bearer ' },
      // 基础素材
      material: {
        text: {
          a: 'left', // 对齐方式
          warp: false, // 是否开启换行
          t: 'text', // 类型
          c: '#000', // 颜色
          bgc: '', // 背景色
          h: 200, // 高度
          w: 200, // 宽度
          x: 100, // x坐标
          y: 100, // y坐标
          fn: 'ali-Regular', // 字体
          s: 68, // 字体大小
          name: '文字', // 名称
          v: '内容', // 内容
          rm: '备注', // 备注
          uuid: '' // 唯一标识
        },
        qrcode: {
          t: 'qrcode', // 类型
          c: '#000000', // 颜色
          h: 150, // 高度
          w: 150, // 宽度
          x: 250, // x坐标
          y: 400, // y坐标
          fn: '', // 字体
          bgc: '#ffffff', // 背景色
          name: '文字', // 名称
          v: 'https://gitee.com/nickbai/freeposter', // 内容
          rm: '备注', // 备注
          uuid: '' // 唯一标识
        },
        img: {
          t: 'image', // 类型
          h: 51, // 高度
          w: 163, // 宽度
          x: 67, // x坐标
          y: 57, // y坐标
          c: '#000000', // 颜色
          bgc: '#fff', // 背景色
          fn: '', // 字体
          name: '图片', // 名称
          v: 'https://poster.prodapi.cn/static/images/xiaoniu.png', // 内容
          rm: '备注', // 备注
          uuid: '' // 唯一标识
        }
      },
      resize: 50, // 缩放比例
      wrapper_style: '',
      bg_style: '',
      // 封面列表
      coverList: [],
      // 可用的模板列表
      posterList: [],
      nowFormIndex: '', // 当前操作的组件下标
      rules: {
        name: [{ required: true, message: '请输入名称' }]
      }
    }
  },
  watch: {
    resize () {
      this.setStyle()
    }
  },
  created () {
    this.apiUrl = process.env.BASE_API
    this.setStyle()
    this.getPosterList()
  },
  methods: {
    // 设置化画布样式
    setStyle () {
      const bgWidth = this.calcSize(this.formData.width, 1) + 'px'
      const bgHeight = this.calcSize(this.formData.height, 1) + 'px'
      this.wrapper_style = 'width:' + bgWidth + ';height:' + bgHeight
      this.bg_style =
        'width:' +
        bgWidth +
        ';height:' +
        bgHeight +
        ';background-size:' +
        bgWidth +
        ' ' +
        bgHeight +
        ';'

      if (this.formData.activeName === 'color') {
        this.bg_style += 'background-color:' + this.formData.color + ';'
      }

      if (this.formData.img_src && this.formData.activeName === 'img') {
        this.bg_style += 'background-image: url(' + this.formData.img_src + ');'
      }

      // 重新绘制 二维码
      this.formData.item.forEach((ele, index) => {
        if (ele.t === 'qrcode') {
          this.$nextTick(() => {
            this.qrcode(index, ele)
          })
        }
      })
    },
    uuid () {
      function S4 () {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
      }
      return S4() + S4()
    },
    // 预览
    async preview () {
      console.log(this.formData)
      const res = await posterApi.preview(this.formData)
      if (res.code === 0) {
        this.previewImg = true
        this.url = res.data
        this.srcList[0] = res.data
      } else {
        this.$message.error(res.msg)
      }
    },
    closeViewer () {
      this.previewImg = false
    },
    calcSize (num, type) {
      let result = ''
      if (type) {
        result = (num * (this.resize / 100)).toFixed(1)
      } else {
        result = parseInt(num * (this.resize / 100))
      }

      return result
    },
    // 下载
    download () {
      if (this.srcList[0]) {
        window.open(this.srcList[0], '_target')
      }
    },
    // 加减尺寸
    changeSize (type) {
      if (type === 1) {
        if (this.resize <= 5) {
          return
        }

        if (this.resize > 30) {
          this.resize -= 10
        } else {
          this.resize -= 1
        }
      } else if (type === 2) {
        if (this.resize >= 300) {
          return
        }

        if (this.resize < 30) {
          this.resize += 1
        } else {
          this.resize += 10
        }
      }

      // 重新渲染 -- 解决组件 无法同时更新 x,y,w,h
      this.formData.item.forEach((ele, index) => {
        ele.uuid = this.uuid()
      })
    },
    // diy设计
    async diy (id) {
      const res = await posterApi.info({ id: id })
      // 基础信息
      this.formData = JSON.parse(res.data.design_content)
      this.formData.qulity = parseInt(this.formData.qulity)

      this.formData.item.forEach((ele, index) => {
        if (ele.t === 'qrcode') {
          this.$nextTick(() => {
            this.qrcode(index, ele)
          })
        }
      })
    },
    qrcode (index, ele) {
      const dom = document.getElementById('qrcode' + index)
      dom.innerHTML = ''
      /* eslint-disable */
      let qrcode = new QRCode(dom, {
        text: encodeURI(ele.v),
        width: (ele.w * (this.resize / 100)).toFixed(1),
        height: (ele.h * (this.resize / 100)).toFixed(1),
        colorDark: ele.c,
        colorLight: ele.bgc,
        correctLevel: QRCode.CorrectLevel.H
      })
    },
    // 删除组件
    delItem() {
      this.formData.item.splice(this.nowFormIndex, 1)
    },
    // 更改二维码内容
    changeQrcode(data) {
      console.log('收到内容', data)
      this.qrcode(data.index, data.item)
    },
    // 二维码变色
    changeColor() {
      this.qrcode(this.nowFormIndex, this.formData.item[this.nowFormIndex])
    },
    // 上传成功
    handleSuccess(res, file) {
      this.cover.source = res.data.url
      this.cover.width = res.data.width
      this.cover.height = res.data.height
      this.cover.type = res.data.type
    },
    // 改变尺寸
    resizing(newRect) {
      this.formData.item[this.nowFormIndex].x = parseInt(
        parseInt(newRect.left) / (this.resize / 100).toFixed(1)
      )

      this.formData.item[this.nowFormIndex].y = parseInt(
        parseInt(newRect.top) / (this.resize / 100).toFixed(1)
      )

      this.formData.item[this.nowFormIndex].w = parseInt(
        parseInt(newRect.width) / (this.resize / 100).toFixed(1)
      )

      this.formData.item[this.nowFormIndex].h = parseInt(
        parseInt(newRect.height) / (this.resize / 100).toFixed(1)
      )

      // 重新绘制二维码
      if (this.formData.item[this.nowFormIndex].t === 'qrcode') {
        this.qrcode(this.nowFormIndex, this.formData.item[this.nowFormIndex])
      }
    },
    // 拖动
    dragging(newRect) {
      this.formData.item[this.nowFormIndex].x = parseInt(
        parseInt(newRect.left) / (this.resize / 100).toFixed(1)
      )

      this.formData.item[this.nowFormIndex].y = parseInt(
        parseInt(newRect.top) / (this.resize / 100).toFixed(1)
      )
    },
    // 激活
    onActivated(index) {
      this.nowFormIndex = index
      if (this.formData.item[index].t === 'text') {
        this.setting_title = '文字'
      } else if (this.formData.item[index].t === 'image') {
        this.setting_title = '图片'
      } else if (this.formData.item[index].t === 'qrcode') {
        this.setting_title = '二维码'
      }

      this.nowWidget = this.formData.item[index]
      this.setting_tab = 'widget_setting'
    },
    // 取消
    onDeactivated(index) {},
    // 监听修改
    baseUpdate(data) {
      if (data.type === 'style') {
        this.formData = data.data
        this.setStyle()
      }
    },
    // 保存入库
    async save() {
      const res = await posterApi.add(this.formData)
      if (res.code == 0) {
        this.$message.success(res.msg)
      } else {
        this.$message.error(res.msg)
      }
    },
    // 添加组件
    addItem(type) {
      if (type == 'text') {
        let item = JSON.parse(JSON.stringify(this.material.text))
        item.uuid = this.uuid()
        this.formData.item.push(item)
      } else if (type == 'image') {
        let item = JSON.parse(JSON.stringify(this.material.img))
        item.uuid = this.uuid()
        this.formData.item.push(item)
      } else if (type == 'qrcode') {
        let item = JSON.parse(JSON.stringify(this.material.qrcode))
        item.uuid = this.uuid()
        let index = this.formData.item.length
        this.formData.item.push(item)

        this.$nextTick(() => {
          this.qrcode(index, item)
        })
      }
    },
    // 撤销
    back() {
      let length = this.formData.item.length
      if (length) {
        this.formData.item.pop()
      }
    },
    // 上传
    showUpload() {
      this.dialogVisible = true
    },
    // 切换菜单
    handleTabClick() {
      if (this.source_tab == 'cover') {
        this.getCoverList()
      } else if (this.source_tab == 'data') {
        this.getPosterList()
      }
    },
    // 获取海报列表
    async getPosterList() {
      const res = await posterApi.list()
      console.log('请求结果', res)
      if (res.code == 0) {
        this.posterList = res.data
      } else {
        this.$message.error(res.msg)
      }
    },
    // 获取封面列表
    async getCoverList() {
      let res = await materialApi.list()
      this.coverList = res.data
    },
    // 上传封面
    uploadCover(formName) {
      this.$refs[formName].validate(async valid => {
        if (valid) {
          let res = await materialApi.add(this.cover)
          if (res.code == 0) {
            this.$message.success(res.msg)
            this.dialogVisible = false

            if (this.source_tab == 'cover') {
              this.getCoverList()
            }
          } else {
            this.$message.error(res.msg)
          }
        }
      })
    },
    // 封面diy
    coverDiy(item) {
      this.formData.name = item.name
      this.formData.type = item.type
      this.formData.width = item.width
      this.formData.height = item.height
      this.formData.activeName = 'img'
      this.formData.img_src = item.source
    },
    // 封面删除
    delCover(id) {
      this.$confirm('您确定要删除该封面吗?删除之后无法恢复！', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          let res = await materialApi.del({ id: id })
          if (res.code == 0) {
            this.$message.success(res.msg)
            this.getCoverList()
          } else {
            this.$message.error(res.msg)
          }
        })
        .catch(() => {})
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    // 图片格式转换方法
    dataURLToBlob(dataurl) {
      let arr = dataurl.split(',')
      let mime = arr[0].match(/:(.*?);/)[1]
      let bstr = atob(arr[1])
      let n = bstr.length
      let u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new Blob([u8arr], { type: mime })
    }
  }
}
</script>

<style scoped>
.container {
  width: 100%;
  height: calc(100% - 60px);
}
.content-box {
  width: 100%;
  height: 100%;
}
.menu {
  height: 100%;
}
.grid-content {
  height: 100%;
  width: 100%;
}
.poster-view {
  height: calc(100vh - 70px);
  overflow: auto;
  background-color: #eef2f8;
}
.header-tool {
  height: 100%;
}
.header-tool div {
  float: right;
  width: 60px;
  margin-top: 13px;
}
.list-wrapper {
  overflow-y: auto;
  height: calc(100vh - 70px);
  padding: 0 10px;
}
.list {
  display: flex;
  flex-wrap: wrap;
}
.free-poster {
  width: 120px;
  display: inline-block;
  margin: 4px;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  border: 1px solid #e0e5ea;
  max-height: 210px;
  height: 210px;
}
.free-poster:hover .free-poster-title {
  display: block;
}
.free-poster:hover .cover-del {
  display: block;
}
.free-poster-title {
  position: absolute;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  padding: 0 5px;
  height: 22px;
  background-color: #2c3e50;
  color: #fff;
  font-size: 12px;
  line-height: 22px;
  display: none;
}
.free-poster img {
  width: 100%;
  height: 100%;
}
.free-editor-wrapper {
  position: relative;
  margin: 0 auto;
  width: 360px;
  height: 640px;
  outline: none;
  box-sizing: initial;
  overflow: visible;
  padding: 70px;
}
.free-poster-bg {
  box-shadow: 1px 1px 15px rgb(0 0 0 / 20%);
  background-repeat: no-repeat;
  width: 360px;
  height: 640px;
  background-color: rgb(250, 251, 252);
  background-size: 360px 640px;
  position: relative;
}
.free-editor-bottom-bar {
  display: flex;
  position: absolute;
  bottom: 150px;
  right: 23%;
  z-index: 999;
  width: 120px;
  justify-content: center;
  box-shadow: 0 2px 8px 0 rgb(0 0 0 / 6%);
  height: 36px;
  background: #fff;
  border-radius: 4px;
  color: #333;
  line-height: 36px;
  font-size: 13px;
}
.free-editor-bottom-bar i {
  width: 36px;
  text-align: center;
  cursor: pointer;
  font-size: 24px;
  line-height: 37px;
}
.free-editor-bottom-bar .scale-num {
  display: block;
  flex-grow: 1;
  text-align: center;
}
.tools-title {
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-bottom: 1px solid #c2c2c2;
}
.free-drag {
  position: absolute;
  z-index: 5;
  box-sizing: border-box;
  cursor: default;
}
.list-wrapper {
  overflow-y: auto;
  height: calc(100vh - 111px);
}
.item {
  border-radius: 4px;
  height: 72px;
  width: 100%;
  color: #33383e;
  align-items: center;
  display: flex;
  cursor: pointer;
  margin-top: 10px;
  background-color: #f6f7f9;
}
.item i {
  font-size: 20px;
  margin-left: 20px;
}
.item h3 {
  font-size: 14px;
  line-height: 18px;
  font-weight: 600;
  margin-bottom: 6px;
  margin-top: 0;
  color: rgba(0, 0, 0, 0.85);
}
.item-desc p {
  margin: 0 0 0 20px;
  color: #7f8792;
  font-size: 12px;
  line-height: 18px;
  padding: 0;
}
.cover-del {
  position: absolute;
  z-index: 100;
  top: 180px;
  left: 94px;
  background: #f84311;
  color: #fff;
  padding: 3px;
  display: none;
}
.cover_img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}
</style>

<style>
.free-poster-tools {
  overflow: auto;
}
.free-poster-tools .el-form-item__label {
  padding: 0;
  font-size: 12px;
}
.free-poster-tools .el-form-item {
  margin-bottom: 5px;
}
#tab-base_setting {
  padding-left: 20px;
}
#tab-data {
  padding-left: 20px;
}
.free-poster-tools .el-input__inner {
  height: 32px;
  line-height: 32px;
}
.free-poster-tools .el-form-item__label {
  line-height: 28px;
}
.free-poster-tools
  .el-input-number.is-controls-right
  .el-input-number__decrease,
.el-input-number.is-controls-right .el-input-number__increase {
  line-height: 16px;
}
.free-poster-tools .el-input-number {
  line-height: 32px;
}
.list-wrapper .el-upload--picture-card {
  width: 120px;
  height: 210px;
  cursor: pointer;
  line-height: 210px;
  margin: 4px;
}
.list-wrapper .el-upload-list--picture-card .el-upload-list__item {
  width: 120px;
  display: inline-block;
  margin: 4px;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  border: 1px solid #e0e5ea;
  max-height: 210px;
  height: 210px;
}
</style>
